package org.smart4j.aopdemo.custom;

import java.lang.reflect.Method;

/**
 * 代理横切模板类
 */
public abstract class AbstractProxy implements Proxy {

    /**
     * 代理模板
     * @param proxyChain
     */
    public void doProxy(ProxyChain proxyChain) {
        Class<?> cls = proxyChain.getTargetClass();
        Method method = proxyChain.getTargetMethod();
        Object[] params = proxyChain.getMethodParams();
        //执行前统一执行
        begin();
        try{
            //是否需要执行切面进行一个判断
            if(filter(cls,method,params)){
                //执行前先执行切面
                before(cls,method,params);
                //这个方法是关键，返回执行下一个代理next proxy，在这个时候是会产生一个相互调用，如果有多个proxy，每个在doProxy反向调它的doProxy，这样子所有before按顺序先执行，完成后返回方法执行，再执行after。
                proxyChain.doProxyChain();
                //执行后执行切面
                after(cls,method,params);
            }else {
                proxyChain.doProxyChain();
            }

        }catch (Throwable e){
            error(cls,method,params,e);
        }finally {
            //调用后统一执行
            end();
        }

    }

    /**
     * 开始执行前执行钩子方法
     */
    public void begin() {
    }

    /**
     * 对是否执行before，after进行过滤计算
     * @param cls 目标类
     * @param method 目标方法
     * @param params 目标方法参数
     * @return true 执行切面方法 false 不执行切面方法
     */
    public boolean filter(Class<?> cls, Method method, Object[] params) {
        return true;
    }

    /**
     * 执行目标方法前切面方法
     * @param cls 目标类
     * @param method 目标方法
     * @param params 目标方法参数
     */
    public void before(Class<?> cls, Method method, Object[] params) {
    }

    /**
     *
     * @param cls
     * @param method
     * @param params
     */
    public void after(Class<?> cls, Method method, Object[] params) {
    }

    /**
     * 执行出错时，执行的切面
     * @param cls
     * @param method
     * @param params
     * @param e
     */
    public void error(Class<?> cls, Method method, Object[] params, Throwable e) {
    }

    /**
     * 执行完成后执行钩子方法
     */
    public void end() {
    }
}
